Alexa公式の日本語FactサンプルスキルをASK SDK v2対応してTypeScriptで書き直してみた
はじめに
Alexaの公式Githubリポジトリで公開されているFactサンプルスキルには、メインの英語版のブランチに加えて、日本語版のブランチがあります。 英語版は先日リリースされたAlexa Skill Kit SDK for Node.js Version 2(以下v2 SDK)に対応したコードに修正が済んでいますが、 残念ながら日本語版はv2 SDK対応がされていません。そこで、日本語版のv2 SDK対応を行い、ついでにスキルのコードをTypeScript化もしてみましたのでその過程をご紹介します。
v2 SDK対応
package.jsonの修正
まずはpackage.jsonのdependenciesでv2 SDKを指定します。
git diff lambda/custom/package.json diff --git a/lambda/custom/package.json b/lambda/custom/package.json index 631590d..c36fd9e 100644 --- a/lambda/custom/package.json +++ b/lambda/custom/package.json @@ -14,6 +14,7 @@ "author": "Amazon.com", "license": "Apache-2.0", "dependencies": { - "alexa-sdk": "^1.0.12" + "ask-sdk": "^2.0.3" } }
index.jsの修正
次にindex.jsを修正します。Alexaの発話内容などの日本語固有の箇所を除いて、v2 SDK対応済みのUS版のindex.jsのコードをコピーします。FallbackIntentとか、US版でしか動かない箇所もありますが、残していても問題無さそうなので今回はそのままにしました。
v2 SDK対応したUS版では、cookbookというユーティリティ関数のモジュールが追加されていて、その中の関数が一つ使用されていました。今回はとりあえず当該関数だけをindex.jsにコピーすることにしました。
修正後のindex.jsはこんな感じになります。
デプロイ&動作確認
ここまでで、いったんスキルをデプロイして動作確認します。
cd lambda/custom npm install --save ask-sdk cd ../.. ask deploy -p XXXX -------------------- Create Skill Project -------------------- Profile for the deployment: [XXXX] Skill Id: XXXXXXXXXXXXXXXX Skill deployment finished. Model deployment finished. Lambda deployment finished. Lambda function(s) created: [URI] XXXXXXXXXXXXXXXX No in-skill product to be deployed. Your skill is now deployed and enabled in the development stage. Try invoking the skill by saying “Alexa, open {your_skill_invocation_name}” or simulate an invocation via the `ask simulate` command.
ask simulate
コマンドは以前は日本語スキルでは使えなかったのですが、ask-cli v1.3.1現在日本語スキルでも使えるようになっていました。
ask simulate -l ja-JP -t "宇宙豆知識をひらいて" -p XXXX
開発者コンソールのテスト画面でも、スキルが問題なく動作することが確認できました。
TypeScript化
無事v2 SDKでスキルが動くようになったので、次はTypeScript化を行います。全体的な作業の流れは以下のブログを参考にしました。
TypeScript開発環境の準備
まずTypeScriptコマンド(tsc
)をインストールします。
npm install -g typescript tsc --version Version 2.8.3
次にNodeの型情報をインストールします。
npm install -g --save-dev @types/node
index.jsをindex.tsにリネームします。
git mv index.js index.ts
tsc
コマンドの設定ファイルtsconfig.jsonを生成して最低限必要な部分を編集します。
tsc --init message TS6071: Successfully created a tsconfig.json file.
cat tsconfig.json { "compilerOptions": { "target": "es6", "module": "commonjs", "strict": true, "esModuleInterop": true, "sourceMap": true, }, "files": [ "index.ts" ] }
index.tsの編集
index.tsをコンパイルが通るように編集していきます。 まず先頭のrequireをimportに変更します。
- const Alexa = require('ask-sdk'); + import * as Alexa from 'ask-sdk';
関数定義の引数に型情報をつけます。
+ canHandle(handlerInput: Alexa.HandlerInput) { - canHandle(handlerInput) { + handle(handlerInput: Alexa.HandlerInput) { - handle(handlerInput) { + handle(handlerInput: Alexa.HandlerInput, error: Error) { - handle(handlerInput, error) {
getRandomItem()のオリジナルのJS実装は引数に任意の型の配列もしくはオブジェクト受け付ける仕様になっています。今回はコンパイルを通すことを優先したいので、引数の型をstring[]に限定した実装に単純化することにしました。
+ function getRandomItem(arrayOfItems: string[]) { + let i = 0; + i = Math.floor(Math.random() * arrayOfItems.length); + return (arrayOfItems[i]); + }
SessionEndedRequestHandler
ではhandlerInput.requestEnvelope.request
のインスタンスがSessionEndedRequest
型で返ってくることになっていて、その型にしかreason
というメンバーは定義されていないので、以下のようにキャストします。
+ handle(handlerInput: Alexa.HandlerInput) { + const request: SessionEndedRequest = <SessionEndedRequest>handlerInput.requestEnvelope.request; + console.log(`Session ended with reason: ${request.reason}`); + + return handlerInput.responseBuilder.getResponse(); + },
今回の編集で利用しようとしている型のimportを追加します。
import { RequestEnvelope, ResponseEnvelope, services, SessionEndedRequest } from 'ask-sdk-model';
修正後のindex.tsはこんな感じになります。
最後に、tsconfig.jsonのあるディレクトリでtsc
コマンドを実行すると、index.tsからindex.jsが生成され、ask deploy
等でAWS Lambdaにデプロイすることができるようになります。
おわりに
tscコマンドの使い方で若干とまどいましたが、 JSからTSへの移殖自体は移植元のコードが単純だったこともあり、サクッとできてしまいました。 今回作業した内容は以下で公開してありますので、TS x v2 SDKでスキル開発をする際の参考にしていただけると幸いです。
GitHub - mayosuke/skill-sample-nodejs-fact at ja-JP